--[[ 
This module provides traditional (and less traditional) functions for setting up single or repeated 
callbacks in MOAI.
]]
module(..., package.seeall)


function once(delay, func, ...)
    --[[ Schedule a function to run after 'delay' seconds. ]]
    local timer = MOAITimer.new()
    timer:setSpan(delay)
    timer:setListener(MOAITimer.EVENT_TIMER_END_SPAN, function() func(...) end)
    timer:start()
    return timer
end

function interval(delay, func, ...)
    --[[ Schedule a function to run every 'delay' seconds (note that the first call to the function 
    is done 'delay' seconds after scheduling). ]]
    if delay <= 0 then
        error(("invalid time interval while scheduling function (%s)"):format(delay), 2)
    end
    local timer = once(delay, func, ...)
    timer:setMode(MOAITimer.LOOP)
    return timer
end

function frame_once(frames, func, ...)
    --[[ Call a function after 'frames' MOAI simulation updates. ]]
    local co = MOAICoroutine.new()
    co:run(elapse_frames, frames, false, func, ...)
    return co
end

function frame_interval(frames, func, ...)
    --[[ Call a function every 'frames' MOAI simulation updates. ]]
    if frames <= 0 then
        error(("invalid frame interval while scheduling function (%s)"):format(frames), 2)
    end
    local co = MOAICoroutine.new()
    co:run(elapse_frames, frames, true, func, ...)
    return co
end

local function elapse_frames(frames, forever, func, ...)
    assert(frames > 0 or not forever)
    while true do
        local elapsed = 0
        while elapsed < frames do
            coroutine.yield()
            elapsed = elapsed + 1
        end
        func(...)
        if not forever then return end
    end
end
